home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / proc / procMisc.c < prev    next >
C/C++ Source or Header  |  1991-04-29  |  45KB  |  1,638 lines

  1. /*
  2.  *  procMisc.c --
  3.  *
  4.  *    Misc. routines to get and set process state.
  5.  *
  6.  * Copyright 1986 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /sprite/src/kernel/proc/RCS/procMisc.c,v 9.16 91/04/29 16:31:46 kupfer Exp $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #include <sprite.h>
  21. #include <proc.h>
  22. #include <status.h>
  23. #include <sync.h>
  24. #include <sched.h>
  25. #include <sig.h>
  26. #include <stdlib.h>
  27. #include <list.h>
  28. #include <string.h>
  29. #include <procInt.h>
  30. #include <rpc.h>
  31. #include <dbg.h>
  32. #include <vm.h>
  33. #include <ctype.h>
  34. #include <fscache.h>
  35. #include <fsutil.h>
  36. #include <rpcClient.h>
  37. #include <rpcServer.h>
  38. #include <procServer.h>
  39. #include <fsrmt.h>
  40. #include <bstring.h>
  41. #include <stdio.h>
  42.  
  43. #define min(a,b) ((a) < (b) ? (a) : (b))
  44. /*
  45.  * Procedures internal to this file
  46.  */
  47.  
  48. static ReturnStatus     GetRemotePCB _ARGS_((int hostID, Proc_PID pid,
  49.                 Proc_PCBInfo *pcbPtr, char *argString));
  50. static void        FillPCBInfo _ARGS_((Proc_ControlBlock *pcbPtr,
  51.                 Proc_PCBInfo *statusInfoPtr));    
  52.  
  53. /*
  54.  *----------------------------------------------------------------------
  55.  *
  56.  * Proc_Init --
  57.  *
  58.  *    Called during startup to initialize data structures.
  59.  *
  60.  * Results:
  61.  *    None.
  62.  *
  63.  * Side effects:
  64.  *    Process table initialized, debug list initialized, locks initialized.
  65.  *
  66.  *----------------------------------------------------------------------
  67.  */
  68.  
  69. void
  70. Proc_Init()
  71. {
  72.     ProcInitTable();
  73.     ProcDebugInit();
  74. }
  75.  
  76.  
  77. /*
  78.  *----------------------------------------------------------------------
  79.  *
  80.  * Proc_GetPCBInfo --
  81.  *
  82.  *    Returns the process control blocks for the specified processes
  83.  *    on the specified host.  If firstPid is equal to PROC_MY_PID
  84.  *    and the hostID is PROC_MY_HOSTID, then the PCB for the current
  85.  *    process is returned.  Otherwise PCBs for all processes in the
  86.  *    range firstPid to lastPid on host hostID are returned.  Only
  87.  *    the index portions of the processIDs for firstPid and lastPid
  88.  *    are relevant. 
  89.  *
  90.  * Results:
  91.  *    SYS_INVALID_ARG -     firstPid was < 0, firstPid > lastPid
  92.  *    SYS_ARG_NOACCESS -     The buffers to store the pcbs in were not
  93.  *                accessible.
  94.  *      *trueNumBuffers is set to be the actual number of
  95.  *    PCBs returned which can be less than the number requested if
  96.  *    lastPid - firstPid is greater than the maximum PCBs available.
  97.  *
  98.  * Side effects:
  99.  *    None.
  100.  *
  101.  *----------------------------------------------------------------------
  102.  */
  103.  
  104. /*
  105.  * Macro to fix up ticks for a process control block.
  106.  */
  107. #define TICKS_TO_TIME(pcbEntry) \
  108.     Timer_TicksToTime(pcbEntry.kernelCpuUsage.ticks,  \
  109.               &pcbEntry.kernelCpuUsage.time); \
  110.     Timer_TicksToTime(pcbEntry.userCpuUsage.ticks,  \
  111.               &pcbEntry.userCpuUsage.time); \
  112.     Timer_TicksToTime(pcbEntry.childKernelCpuUsage.ticks,  \
  113.               &pcbEntry.childKernelCpuUsage.time); \
  114.     Timer_TicksToTime(pcbEntry.childUserCpuUsage.ticks,  \
  115.               &pcbEntry.childUserCpuUsage.time);
  116.  
  117.  
  118. ReturnStatus
  119. Proc_GetPCBInfo(firstPid, lastPid, hostID, infoSize, bufferPtr, 
  120.         argsPtr, trueNumBuffersPtr)
  121.     Proc_PID         firstPid;         /* First pid to get info for. */
  122.     Proc_PID        lastPid;         /* Last pid to get info for. */
  123.     int            hostID;             /* Host ID to get info for. */
  124.     int            infoSize;            /* Size of structure */
  125.     Address         bufferPtr;         /* Pointer to buffers. */
  126.     Proc_PCBArgString    *argsPtr;         /* Pointer to argument strings. */
  127.     int         *trueNumBuffersPtr;  /* The actual number of buffers 
  128.                         used.*/
  129. {
  130.     register Proc_ControlBlock     *procPtr = (Proc_ControlBlock *) NIL;
  131.     int                i, j;
  132.     char             argString[PROC_PCB_ARG_LENGTH];
  133.     Proc_ControlBlock        pcbEntry;
  134.     Boolean            remote = FALSE;
  135.     Proc_PID            processID = firstPid;
  136.     ReturnStatus        status = SUCCESS;
  137.     Proc_PCBInfo        statusInfo;
  138.     int                bytesToCopy;
  139.  
  140.  
  141.     if (firstPid != PROC_MY_PID) {
  142.     firstPid &= PROC_INDEX_MASK;
  143.     lastPid &= PROC_INDEX_MASK;
  144.     if ((firstPid > lastPid) ||
  145.         ((firstPid == PROC_MY_PID) && hostID != PROC_MY_HOSTID)) {
  146.         return(GEN_INVALID_ARG);
  147.     }
  148.     }
  149.     if (bufferPtr == USER_NIL) {
  150.     return (SYS_ARG_NOACCESS);
  151.     }
  152.     if (hostID != PROC_MY_HOSTID &&
  153.     (hostID <= 0 || hostID > NET_NUM_SPRITE_HOSTS)) {
  154.     return(GEN_INVALID_ARG);
  155.     }
  156.  
  157.     bytesToCopy = min(sizeof(Proc_PCBInfo), infoSize);
  158.     /*
  159.      * Determine whether to get process table entries for this machine.
  160.      * Currently, the information for this machine is returned unless
  161.      * another machine is explicitly specified; i.e., migrated processes
  162.      * get information for their current machine rather than their home.
  163.      */
  164.  
  165.     if (hostID == PROC_MY_HOSTID) {
  166. #ifdef FORWARD_MIGRATED_GET_PCBS
  167.     procPtr = Proc_GetCurrentProc();
  168.     Proc_Lock(procPtr);
  169.     if (procPtr->genFlags & PROC_FOREIGN) {
  170.         hostID = procPtr->peerHostID;
  171.         processID = procPtr->peerHostID;
  172.         remote = TRUE;
  173.     } 
  174.     Proc_Unlock(procPtr);
  175. #endif /* FORWARD_MIGRATED_GET_PCBS */
  176.     } else if (hostID != rpc_SpriteID) {
  177.     remote = TRUE;
  178.     }
  179.  
  180.     if (firstPid == PROC_MY_PID) {
  181.     /*
  182.      *  Return PCB for the current process.
  183.      */
  184.     procPtr = Proc_GetCurrentProc();
  185.     if (!remote) {
  186.         bcopy((Address)procPtr, (Address)&pcbEntry,
  187.             sizeof (Proc_ControlBlock));
  188.         TICKS_TO_TIME(pcbEntry);
  189.         FillPCBInfo(&pcbEntry, &statusInfo);
  190.     } else {
  191.         status = GetRemotePCB(hostID, processID, &statusInfo,
  192.                        argString);
  193.         if (status != SUCCESS) {
  194.         return(status);
  195.         }
  196.     }
  197.     if (Proc_ByteCopy(FALSE, bytesToCopy,
  198.         (Address)&statusInfo, (Address) bufferPtr) != SUCCESS) {
  199.         return(SYS_ARG_NOACCESS);
  200.     }
  201.     if (argsPtr != (Proc_PCBArgString *) USER_NIL) {
  202.         if (!remote) {
  203.         if (procPtr->argString != (Address) NIL) {
  204.             (void) strncpy(argString, procPtr->argString,
  205.                 PROC_PCB_ARG_LENGTH - 1);
  206.             argString[PROC_PCB_ARG_LENGTH - 1] = '\0';
  207.         } else {
  208.             argString[0] = '\0';
  209.         }
  210.         }
  211.         if (Proc_ByteCopy(FALSE, PROC_PCB_ARG_LENGTH, argString,
  212.                   (Address) argsPtr) != SUCCESS) {
  213.         return(SYS_ARG_NOACCESS);
  214.         }
  215.     }
  216.     } else {
  217.     
  218.     /*
  219.      * Return PCB for all processes or enough to fill all of
  220.      * the buffers, whichever comes first.
  221.      */
  222.  
  223.     
  224.     for (i = firstPid, j = 0; 
  225.          i <= lastPid; 
  226.          i++, j++, (Address) bufferPtr += infoSize) {
  227.         if (!remote) {
  228.         if (i >= proc_MaxNumProcesses) {
  229.             break;
  230.         }
  231.         procPtr = Proc_GetPCB(i);
  232.         if (procPtr == (Proc_ControlBlock *) NIL) {
  233.             panic("Proc_GetInfo: procPtr == NIL!\n");
  234.             status = FAILURE;
  235.             break;
  236.         }
  237.         bcopy((Address)procPtr, (Address)&pcbEntry,
  238.             sizeof (Proc_ControlBlock));
  239.  
  240.         TICKS_TO_TIME(pcbEntry);
  241.         FillPCBInfo(&pcbEntry, &statusInfo);
  242.         } else {
  243.         status = GetRemotePCB(hostID, (Proc_PID) i, &statusInfo,
  244.                        argString);
  245.         if (status != SUCCESS) {
  246.             /*
  247.              * Break if we hit an error.  The typical error condition
  248.              * is to hit an invalid process ID, which happens since
  249.              * we don't know proc_MaxNumProcesses on the other
  250.              * machine.  Instead, we convert GEN_INVALID_ARG to
  251.              * SUCCESS and return what we found so far.
  252.              */
  253.             if (status == GEN_INVALID_ARG) {
  254.             status = SUCCESS;
  255.             }
  256.             break;
  257.         }
  258.         }
  259.         if (Proc_ByteCopy(FALSE, bytesToCopy,
  260.             (Address)&statusInfo, (Address) bufferPtr) != SUCCESS) {
  261.         return(SYS_ARG_NOACCESS);
  262.         }
  263.         if (argsPtr != (Proc_PCBArgString *) USER_NIL) {
  264.         if (!remote) {
  265.             if (procPtr->argString != (Address) NIL) {
  266.             (void) strncpy(argString, procPtr->argString,
  267.                        PROC_PCB_ARG_LENGTH - 1);
  268.             argString[PROC_PCB_ARG_LENGTH - 1] = '\0';
  269.             } else {
  270.             argString[0] = '\0';
  271.             }
  272.         }
  273.         if (Proc_ByteCopy(FALSE, PROC_PCB_ARG_LENGTH, argString,
  274.                   (Address) &(argsPtr[j])) != SUCCESS) {
  275.             return(SYS_ARG_NOACCESS);
  276.         }
  277.         }
  278.     }
  279.  
  280.     if (trueNumBuffersPtr != USER_NIL) {
  281.         if (Proc_ByteCopy(FALSE, sizeof(j), (Address) &j, 
  282.                 (Address) trueNumBuffersPtr) != SUCCESS) {
  283.         return(SYS_ARG_NOACCESS);
  284.         }
  285.     }
  286.     }
  287.  
  288.     return(status);
  289. }
  290.  
  291.  
  292.  
  293. /*
  294.  * Define some constants used to distinguish RPC sub-commands.
  295.  */
  296. #define GET_PCB 1
  297. #define GET_SEG_INFO 2
  298.  
  299. /*
  300.  *----------------------------------------------------------------------
  301.  *
  302.  * GetRemotePCB --
  303.  *
  304.  *    Perform an RPC to get a process control block from another host.
  305.  *
  306.  * Results:
  307.  *    The return status from the RPC is returned.  
  308.  *
  309.  * Side effects:
  310.  *    None.
  311.  *
  312.  *----------------------------------------------------------------------
  313.  */
  314.  
  315. static ReturnStatus    
  316. GetRemotePCB(hostID, pid, pcbPtr, argString)
  317.     int        hostID;        /* Host to send RPC to. */
  318.     Proc_PID    pid;        /* index of PCB to obtain. */
  319.     Proc_PCBInfo *pcbPtr;    /* Place to return PCB data. */
  320.     char    *argString;    /* Place to return argument string. */
  321. {
  322.     Rpc_Storage        storage;
  323.     ReturnStatus     status;
  324.     int            request;
  325.  
  326.     request = GET_PCB;
  327.     storage.requestParamPtr = (Address)&request;
  328.     storage.requestParamSize = sizeof(request);
  329.     storage.requestDataPtr = (Address)&pid;
  330.     storage.requestDataSize = sizeof(Proc_PID);
  331.     storage.replyParamPtr = (Address)pcbPtr;
  332.     storage.replyParamSize = sizeof(Proc_PCBInfo);
  333.     storage.replyDataPtr = (Address)argString;
  334.     storage.replyDataSize = PROC_PCB_ARG_LENGTH;
  335.  
  336.     status = Rpc_Call(hostID, RPC_PROC_GETPCB, &storage);
  337.     if (status == SUCCESS && storage.replyDataSize == 0) {
  338.     argString[0] = '\0';
  339.     }
  340.     return(status);
  341.  
  342. }
  343. /*
  344.  *----------------------------------------------------------------------
  345.  *
  346.  * Proc_GetRemoteSegInfo --
  347.  *
  348.  *    Perform an RPC to get info for a VM segment control from another host.
  349.  *
  350.  * Results:
  351.  *    The return status from the RPC is returned.  
  352.  *
  353.  * Side effects:
  354.  *    None.
  355.  *
  356.  *----------------------------------------------------------------------
  357.  */
  358.  
  359. ReturnStatus    
  360. Proc_GetRemoteSegInfo(hostID, segNum, segInfoPtr)
  361.     int        hostID;        /* Host to send RPC to. */
  362.     int        segNum;        /* index of segment to obtain. */
  363.     Vm_SegmentInfo *segInfoPtr;    /* Place to return segment data. */
  364. {
  365.     Rpc_Storage        storage;
  366.     ReturnStatus     status;
  367.     int            request;
  368.  
  369.     request = GET_SEG_INFO;
  370.     storage.requestParamPtr = (Address)&request;
  371.     storage.requestParamSize = sizeof(request);
  372.     storage.requestDataPtr = (Address)&segNum;
  373.     storage.requestDataSize = sizeof(int);
  374.     storage.replyParamPtr = (Address)segInfoPtr;
  375.     storage.replyParamSize = sizeof(Vm_SegmentInfo);
  376.     storage.replyDataPtr = (Address)NIL;
  377.     storage.replyDataSize = 0;
  378.  
  379.     status = Rpc_Call(hostID, RPC_PROC_GETPCB, &storage);
  380.     return(status);
  381.  
  382. }
  383.  
  384. /*
  385.  *----------------------------------------------------------------------
  386.  *
  387.  * FillPCBInfo --
  388.  *
  389.  *    Fills in a Proc_PCBInfo structure from the contents of a
  390.  *    control block.
  391.  *
  392.  * Results:
  393.  *    None.
  394.  *
  395.  * Side effects:
  396.  *    None.
  397.  *
  398.  *----------------------------------------------------------------------
  399.  */
  400.  
  401. static void
  402. FillPCBInfo(pcbPtr, statusInfoPtr)
  403.     Proc_ControlBlock        *pcbPtr;     /* Ptr to pcb to convert */
  404.     Proc_PCBInfo        *statusInfoPtr; /* Structure to fill in */
  405. {
  406.     int     i;
  407.  
  408.     statusInfoPtr->processor = pcbPtr->processor;
  409.     statusInfoPtr->state = pcbPtr->state;
  410.     statusInfoPtr->genFlags = pcbPtr->genFlags;
  411.     statusInfoPtr->processID = pcbPtr->processID;
  412.     statusInfoPtr->parentID = pcbPtr->parentID;
  413.     statusInfoPtr->familyID = pcbPtr->familyID;
  414.     statusInfoPtr->userID = pcbPtr->userID;
  415.     statusInfoPtr->effectiveUserID = pcbPtr->effectiveUserID;
  416.     statusInfoPtr->event = pcbPtr->event;
  417.     statusInfoPtr->billingRate = pcbPtr->billingRate;
  418.     statusInfoPtr->recentUsage = pcbPtr->recentUsage;
  419.     statusInfoPtr->weightedUsage = pcbPtr->weightedUsage;
  420.     statusInfoPtr->unweightedUsage = pcbPtr->unweightedUsage;
  421.     statusInfoPtr->kernelCpuUsage = pcbPtr->kernelCpuUsage.time;
  422.     statusInfoPtr->userCpuUsage = pcbPtr->userCpuUsage.time;
  423.     statusInfoPtr->childKernelCpuUsage = pcbPtr->childKernelCpuUsage.time;
  424.     statusInfoPtr->childUserCpuUsage = pcbPtr->childUserCpuUsage.time;
  425.     statusInfoPtr->numQuantumEnds = pcbPtr->numQuantumEnds;
  426.     statusInfoPtr->numWaitEvents = pcbPtr->numWaitEvents;
  427.     statusInfoPtr->schedQuantumTicks = pcbPtr->schedQuantumTicks;
  428.     for(i = 0; i < VM_NUM_SEGMENTS; i++) {
  429.     if (pcbPtr->vmPtr != (Vm_ProcInfo *) NIL && 
  430.         pcbPtr->vmPtr->segPtrArray[i] != (Vm_Segment *) NIL) {
  431.         statusInfoPtr->vmSegments[i] = 
  432.         (Vm_SegmentID) pcbPtr->vmPtr->segPtrArray[i]->segNum;
  433.     } else {
  434.         statusInfoPtr->vmSegments[i] = (Vm_SegmentID) -1;
  435.     }
  436.     }
  437.     statusInfoPtr->sigHoldMask = pcbPtr->sigHoldMask;
  438.     statusInfoPtr->sigPendingMask = pcbPtr->sigPendingMask;
  439.     for(i = 0; i < SIG_NUM_SIGNALS; i++) {
  440.     statusInfoPtr->sigActions[i] = pcbPtr->sigActions[i];
  441.     }
  442.     statusInfoPtr->peerHostID = pcbPtr->peerHostID;
  443.     statusInfoPtr->peerProcessID = pcbPtr->peerProcessID;
  444. }
  445.  
  446.  
  447. /*
  448.  *----------------------------------------------------------------------
  449.  *
  450.  * Proc_RpcGetPCB --
  451.  *
  452.  *    Stub to handle a remote request for a PCB or Vm_Segment.
  453.  *
  454.  * Results:
  455.  *    Status of reply:
  456.  *    GEN_INVALID_ARG - index into table of process control blocks is
  457.  *              invalid, or segment is invalid.
  458.  *    SUCCESS     - information is returned.
  459.  *
  460.  *    SUCCESS is passed to the caller on this machine.
  461.  *
  462.  * Side effects:
  463.  *    Reply is sent.
  464.  *
  465.  *----------------------------------------------------------------------
  466.  */
  467. /*ARGSUSED*/
  468. ReturnStatus    
  469. Proc_RpcGetPCB(srvToken, clientID, command, storagePtr)
  470.     ClientData          srvToken;    /* Handle on server process passed to
  471.                       * Rpc_Reply */
  472.     int          clientID;    /* Sprite ID of client host */
  473.     int          command;    /* Command identifier */
  474.     register Rpc_Storage *storagePtr;    /* The request fields refer to the 
  475.                      * request buffers and also indicate 
  476.                      * the exact amount of data in the 
  477.                      * request buffers.  The reply fields 
  478.                      * are initialized to NIL for the
  479.                       * pointers and 0 for the lengths.  
  480.                      * This can be passed to Rpc_Reply */
  481. {
  482.     ReturnStatus    status = SUCCESS;
  483.     Proc_PID        *pidPtr;
  484.     Rpc_ReplyMem    *replyMemPtr;
  485.     Proc_PCBInfo    *pcbPtr;
  486.     Proc_ControlBlock   *procPtr = (Proc_ControlBlock *) NIL;
  487.     Proc_ControlBlock   pcb;
  488.     int            *segNumPtr;
  489.     Vm_SegmentInfo    *segInfoPtr;
  490.     int            *requestPtr;
  491.  
  492.     requestPtr = (int *) storagePtr->requestParamPtr;
  493.     if (*requestPtr == GET_SEG_INFO) {
  494.     segNumPtr = (int *) storagePtr->requestDataPtr;
  495.     segInfoPtr = (Vm_SegmentInfo *) malloc(sizeof (Vm_SegmentInfo));
  496.     status = Vm_EncapSegInfo(*segNumPtr, segInfoPtr);
  497.     storagePtr->replyParamPtr = (Address) segInfoPtr;
  498.     storagePtr->replyParamSize = sizeof(Vm_SegmentInfo);
  499.     goto done;
  500.     } else if (*requestPtr == GET_PCB) {
  501.     pidPtr = (Proc_PID *) storagePtr->requestDataPtr;
  502.     if (*pidPtr >= proc_MaxNumProcesses) {
  503.         status = GEN_INVALID_ARG;
  504.     } else {
  505.         procPtr = Proc_GetPCB(*pidPtr);
  506.         if (procPtr == (Proc_ControlBlock *) NIL) {
  507.         panic("Proc_RpcGetPCB: found nil PCB!");
  508.         status = FAILURE;
  509.         }
  510.     }
  511.     if (status != SUCCESS) {
  512.         Rpc_Reply(srvToken, status, storagePtr,
  513.               (int(*)())NIL, (ClientData)NIL);
  514.         return(SUCCESS);
  515.     }
  516.  
  517.     bcopy((Address) procPtr, (Address) &pcb, sizeof (Proc_ControlBlock));
  518.     TICKS_TO_TIME(pcb);
  519.     pcbPtr = (Proc_PCBInfo *) malloc(sizeof (Proc_PCBInfo));
  520.     storagePtr->replyParamPtr = (Address) pcbPtr;
  521.     storagePtr->replyParamSize = sizeof(Proc_PCBInfo);
  522.     FillPCBInfo(&pcb, pcbPtr);
  523.  
  524.     if (procPtr->argString != (Address) NIL) {
  525.         storagePtr->replyDataSize = strlen(procPtr->argString) + 1;
  526.         storagePtr->replyDataPtr = (Address) malloc(storagePtr->replyDataSize);
  527.         (void) strcpy(storagePtr->replyDataPtr, procPtr->argString);
  528.     } else {
  529.         storagePtr->replyDataSize = 0;
  530.         storagePtr->replyDataPtr = (Address) NIL;
  531.     }
  532.     }
  533.     done:
  534.     replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  535.     replyMemPtr->paramPtr = storagePtr->replyParamPtr;
  536.     replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  537.  
  538.     Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  539.         (ClientData) replyMemPtr);
  540.     return(SUCCESS);
  541. }
  542.  
  543.  
  544. /*
  545.  *----------------------------------------------------------------------
  546.  *
  547.  * Proc_GetResUsage --
  548.  *
  549.  *    Returns the resource usage for a process.
  550.  *
  551.  * Results:
  552.  *    SYS_INVALID_ARG -     buffer address was invalid.
  553.  *    PROC_INVALID_PID -     The pid was out-of-range or specified a
  554.  *                non-existent process.
  555.  *    SYS_ARG_NOACCESS -     The buffers to store the pcbs in were not
  556.  *                accessible.
  557.  *
  558.  * Side effects:
  559.  *    None.
  560.  *
  561.  *----------------------------------------------------------------------
  562.  */
  563.  
  564. ReturnStatus
  565. Proc_GetResUsage(pid, bufferPtr)
  566.     Proc_PID         pid;
  567.     Proc_ResUsage     *bufferPtr;         
  568. {
  569.     register Proc_ControlBlock     *procPtr;
  570.     Proc_ResUsage         resUsage;         
  571.     ReturnStatus        status = SUCCESS;
  572.  
  573.     if (pid == PROC_MY_PID) {
  574.     procPtr = Proc_GetEffectiveProc();
  575.     if (procPtr == (Proc_ControlBlock *) NIL) {
  576.         panic("Proc_GetResUsage: procPtr == NIL\n");
  577.     } 
  578.     Proc_Lock(procPtr);
  579.     } else {
  580.     procPtr = Proc_LockPID(pid);
  581.         if (procPtr == (Proc_ControlBlock *) NIL) {
  582.             return (PROC_INVALID_PID);
  583.         }
  584.     }
  585.  
  586.     /*
  587.      *  Copy the information to the out parameters.
  588.      */
  589.  
  590.     if (bufferPtr == USER_NIL) {
  591.     status = SYS_INVALID_ARG;
  592.     } else {
  593.     Timer_TicksToTime(procPtr->kernelCpuUsage.ticks,
  594.               &resUsage.kernelCpuUsage);
  595.     Timer_TicksToTime(procPtr->userCpuUsage.ticks, &resUsage.userCpuUsage);
  596.     Timer_TicksToTime(procPtr->childKernelCpuUsage.ticks, 
  597.                 &resUsage.childKernelCpuUsage);
  598.     Timer_TicksToTime(procPtr->childUserCpuUsage.ticks,
  599.                 &resUsage.childUserCpuUsage);
  600.     resUsage.numQuantumEnds = procPtr->numQuantumEnds;
  601.     resUsage.numWaitEvents     = procPtr->numWaitEvents;
  602.  
  603.     if (Proc_ByteCopy(FALSE, sizeof(Proc_ResUsage), 
  604.         (Address) &resUsage, (Address) bufferPtr) != SUCCESS){
  605.         status = SYS_ARG_NOACCESS;
  606.     }
  607.     }
  608.     Proc_Unlock(procPtr);
  609.     return(status);
  610. }
  611.  
  612.  
  613. /*
  614.  *----------------------------------------------------------------------
  615.  *
  616.  * Proc_GetPriority --
  617.  *
  618.  *    Returns the priority of a process.
  619.  *
  620.  * Results:
  621.  *    SYS_INVALID_ARG -     priorityPtr address was invalid.
  622.  *    PROC_INVALID_PID -     The pid was out-of-range or specified a
  623.  *                non-existent process.
  624.  *    SYS_ARG_NOACCESS -     The buffer to store the priority was not
  625.  *                accessible.
  626.  *
  627.  * Side effects:
  628.  *    None.
  629.  *
  630.  *----------------------------------------------------------------------
  631.  */
  632.  
  633. ReturnStatus
  634. Proc_GetPriority(pid, priorityPtr)
  635.     Proc_PID pid;    /* ID of process whose priority is to be returned. */
  636.     int *priorityPtr;    /* Priority returned by Proc_GetPriority. */
  637. {
  638.     register Proc_ControlBlock     *procPtr;
  639.     ReturnStatus        status = SUCCESS;
  640.  
  641.     if (pid == PROC_MY_PID) {
  642.     procPtr = Proc_GetEffectiveProc();
  643.     if (procPtr == (Proc_ControlBlock *) NIL) {
  644.         panic("Proc_GetPriority: procPtr == NIL\n");
  645.     } 
  646.     Proc_Lock(procPtr);
  647.     } else {
  648.     procPtr = Proc_LockPID(pid);
  649.         if (procPtr == (Proc_ControlBlock *) NIL) {
  650.             return (PROC_INVALID_PID);
  651.         }
  652.     }
  653.  
  654.     /*
  655.      *  Copy the information to the out parameter.
  656.      */
  657.  
  658.     if (priorityPtr == USER_NIL) {
  659.     status = SYS_INVALID_ARG;
  660.     } else {
  661.     if (Proc_ByteCopy(FALSE, sizeof(int),
  662.              (Address) &(procPtr->billingRate),
  663.             (Address) priorityPtr) != SUCCESS) {
  664.         status = SYS_ARG_NOACCESS;
  665.     }
  666.     }
  667.     Proc_Unlock(procPtr);
  668.     return(status);
  669. }
  670.  
  671.  
  672. /*
  673.  *----------------------------------------------------------------------
  674.  *
  675.  * Proc_SetPriority --
  676.  *
  677.  *    Sets the priority for a process.
  678.  *
  679.  * Results:
  680.  *    PROC_INVALID_PID -     The pid was out-of-range or specified a
  681.  *                non-existent process.
  682.  *
  683.  * Side effects:
  684.  *    None.
  685.  *
  686.  *----------------------------------------------------------------------
  687.  */
  688.  
  689. ReturnStatus
  690. Proc_SetPriority(pid, priority, useFamily)
  691.     Proc_PID     pid;        /* ID of process whose priority is to be set. */
  692.     int     priority;    /* New scheduling priority for pid. */
  693.     Boolean     useFamily;    /* If TRUE, use pid as the head of a process 
  694.                  * family, and set the priority of every 
  695.                  * process in the family. */
  696. {
  697.     register Proc_ControlBlock     *procPtr;
  698.     register Proc_PCBLink    *procLinkPtr;
  699.     List_Links            *familyList;
  700.     int                userID;
  701.     ReturnStatus        status;
  702.  
  703.     if (priority > PROC_MAX_PRIORITY) {
  704.     priority = PROC_MAX_PRIORITY;
  705.     } else if (priority < PROC_MIN_PRIORITY) {
  706.     priority = PROC_MIN_PRIORITY;
  707.     }
  708.  
  709.     if (useFamily) {
  710.     /*
  711.      * Set priorities of processes in family.
  712.      */
  713.     status = Proc_LockFamily((int) pid, &familyList, &userID);
  714.     if (status != SUCCESS) {
  715.         return(status);
  716.     }
  717.     if (!Proc_HasPermission(userID)) {
  718.         Proc_UnlockFamily((int) pid);
  719.         return(PROC_UID_MISMATCH);
  720.     }
  721.     LIST_FORALL(familyList, (List_Links *) procLinkPtr) {
  722.         procPtr = procLinkPtr->procPtr;
  723.         Proc_Lock(procPtr);
  724.         procPtr->billingRate = priority;
  725.         Proc_Unlock(procPtr);
  726.     }
  727.     Proc_UnlockFamily((int) pid);
  728.     } else {
  729.     /*
  730.      * Set the individual process's priority.
  731.      */
  732.     if (pid == PROC_MY_PID) {
  733.         procPtr = Proc_GetEffectiveProc();
  734.         Proc_Lock(procPtr);
  735.     } else {
  736.         procPtr = Proc_LockPID(pid);
  737.         if (procPtr == (Proc_ControlBlock *) NIL) {
  738.         return (PROC_INVALID_PID);
  739.         }
  740.         if (!Proc_HasPermission(procPtr->effectiveUserID)) {
  741.         Proc_Unlock(procPtr);
  742.         return(PROC_UID_MISMATCH);
  743.         }
  744.     }
  745.     procPtr->billingRate = priority;
  746.     Proc_Unlock(procPtr);
  747.     }
  748.  
  749.     return(SUCCESS);
  750. }
  751.  
  752.  
  753. /*
  754.  *----------------------------------------------------------------------
  755.  *
  756.  * Proc_Profile --
  757.  *
  758.  *    Starts profiling the memory accesses of the current process.
  759.  *
  760.  * Results:
  761.  *    SUCCESS        -    always returned for now.
  762.  *
  763.  * Side effects:
  764.  *    None.
  765.  *
  766.  *----------------------------------------------------------------------
  767.  */
  768.  
  769. /*ARGSUSED*/
  770. ReturnStatus
  771. Proc_Profile(shiftSize, lowPC, highPC, interval, counterArray)
  772.     int shiftSize;    /* # of bits to shift the PC to the right. */
  773.     int lowPC;        /* The lowest PC to profile. */
  774.     int highPC;        /* The highest PC to profile. */
  775.     Time interval;    /* The time interval at which the PC is sampled. */
  776.     int counterArray[];    /* Counters used to count instruction executions. */
  777. {
  778.     return(SUCCESS);
  779. }
  780.  
  781.  
  782. /*
  783.  *----------------------------------------------------------------------
  784.  *
  785.  * Proc_Dump --
  786.  *
  787.  *    Prints out an abbreviated proc table for debugging purposes.
  788.  *
  789.  * Results:
  790.  *    SUCCESS.
  791.  *
  792.  * Side effects:
  793.  *    Prints stuff to screen.
  794.  *
  795.  *
  796.  *----------------------------------------------------------------------
  797.  */
  798.  
  799. ReturnStatus
  800. Proc_Dump()
  801. {
  802.     int i;
  803.     Proc_ControlBlock *pcbPtr;
  804.  
  805.     printf("\n%8s %5s %10s %10s %8s %8s   %s\n",
  806.     "ID", "wtd", "user", "kernel", "event", "state", "name");
  807.     
  808.     for (i = 0; i < proc_MaxNumProcesses; i++) {
  809.     pcbPtr = proc_PCBTable[i];
  810.     if (pcbPtr->state != PROC_UNUSED) {
  811.         Proc_DumpPCB(pcbPtr);
  812.     }
  813.     }
  814.     return(SUCCESS);
  815. }
  816.  
  817.  
  818. /*
  819.  *----------------------------------------------------------------------
  820.  *
  821.  * Proc_DumpPCB --
  822.  *
  823.  *    Prints out the contents of a PCB for debugging purposes.
  824.  *
  825.  * Results:
  826.  *    None.
  827.  *
  828.  * Side effects:
  829.  *    Prints stuff to the screen.
  830.  *
  831.  *----------------------------------------------------------------------
  832.  */
  833.  
  834. void
  835. Proc_DumpPCB(procPtr)
  836.     Proc_ControlBlock *procPtr;
  837. {
  838.  
  839.     Time    kernelTime, userTime;
  840.  
  841. #define DEBUG_INDEX    0x9
  842.  
  843.     static char *states[] = {
  844.     "unused",
  845.     "running",
  846.     "ready",
  847.     "waiting",
  848.     "exiting",
  849.     "dead",
  850.     "migrated",
  851.     "new",
  852.     "suspended",
  853.     "debug",
  854.     };
  855.     Proc_State state;
  856.  
  857.     state = procPtr->state;
  858.     switch (state) {
  859.     case PROC_UNUSED:
  860.     case PROC_RUNNING:
  861.     case PROC_READY:
  862.     case PROC_WAITING:
  863.     case PROC_EXITING:
  864.     case PROC_DEAD:
  865.     case PROC_MIGRATED:
  866.     case PROC_NEW:
  867.         break;
  868.     case PROC_SUSPENDED:
  869.         /* If process is suspended for debugging print "debug" for its
  870.          * state.
  871.          */
  872.         if (procPtr->genFlags & (PROC_DEBUGGED | PROC_ON_DEBUG_LIST)) {
  873.         state = (Proc_State)DEBUG_INDEX;
  874.         }
  875.         break;
  876.     default:
  877.         printf("Warning: Proc_DumpPCB: process %x has invalid process state: %x.\n",
  878.            procPtr->processID, state);
  879.         return;
  880.     }
  881.     /*
  882.      * A header describing the fields has already been printed.
  883.      */
  884.     Timer_TicksToTime(procPtr->userCpuUsage.ticks, &userTime);
  885.     Timer_TicksToTime(procPtr->kernelCpuUsage.ticks, &kernelTime);
  886.     printf("%8x %5d [%1d,%6d] [%1d,%6d] %8x %8s",
  887.            procPtr->processID, 
  888.            procPtr->weightedUsage, 
  889.            userTime.seconds,
  890.            userTime.microseconds,
  891.            kernelTime.seconds, 
  892.            kernelTime.microseconds,
  893.            procPtr->event,
  894.            states[(int) state]);
  895.     if (procPtr->argString != (Address) NIL) {
  896.     char cmd[30];
  897.     char *space;
  898.  
  899.     (void) strncpy(cmd, procPtr->argString, 30);
  900.     space = strchr(cmd, ' ');
  901.     if (space != (char *) NULL) {
  902.         *space = '\0';
  903.     }
  904.     printf(" %s\n", cmd);
  905.     } else {
  906.     printf("\n");
  907.     }
  908. }
  909.  
  910. /*
  911.  *----------------------------------------------------------------------
  912.  *
  913.  * Proc_KillAllProcesses --
  914.  *
  915.  *    Send the kill signal to all processes in the proc table except for
  916.  *    the caller.  If userProcsOnly is TRUE only send signals to user 
  917.  *    processes.
  918.  *
  919.  * Results:
  920.  *    The number of runnable and waiting processes.
  921.  *
  922.  * Side effects:
  923.  *    The kill signal bit is set for all processes.
  924.  *
  925.  *----------------------------------------------------------------------
  926.  */
  927. int
  928. Proc_KillAllProcesses(userProcsOnly)
  929.     Boolean    userProcsOnly;    /* TRUE if only kill user processes. */
  930. {
  931.     register int i;
  932.     register Proc_ControlBlock    *pcbPtr;
  933.     Proc_ControlBlock        *curProcPtr;
  934.     int                alive = 0;
  935.  
  936.     curProcPtr = Proc_GetActualProc();
  937.  
  938.     for (i = 0; i < proc_MaxNumProcesses; i++) {
  939.     pcbPtr = proc_PCBTable[i];
  940.     if (pcbPtr == curProcPtr || pcbPtr->state == PROC_UNUSED ||
  941.         (userProcsOnly && !(pcbPtr->genFlags & PROC_USER))) {
  942.         continue;
  943.     }
  944.     Proc_Lock(pcbPtr);
  945.     if (pcbPtr->state == PROC_RUNNING ||
  946.         pcbPtr->state == PROC_READY ||
  947.         pcbPtr->state == PROC_WAITING ||
  948.         pcbPtr->state == PROC_MIGRATED) {
  949.         alive++;
  950.         (void) Sig_SendProc(pcbPtr, SIG_KILL, 0, (Address)0);
  951.     }
  952.     Proc_Unlock(pcbPtr);
  953.     }
  954.  
  955.     return(alive);
  956. }
  957.  
  958.  
  959. /*
  960.  *----------------------------------------------------------------------
  961.  *
  962.  * Proc_WakeupAllProcesses --
  963.  *
  964.  *    Wakup all waiting processes.
  965.  *
  966.  * Results:
  967.  *    None.
  968.  *
  969.  * Side effects:
  970.  *    All waiting processes are awakened.
  971.  *
  972.  *----------------------------------------------------------------------
  973.  */
  974. void
  975. Proc_WakeupAllProcesses()
  976. {
  977.     register int        i;
  978.     register Proc_ControlBlock    *pcbPtr;
  979.     Proc_ControlBlock        *curProcPtr;
  980.  
  981.     curProcPtr = Proc_GetActualProc();
  982.  
  983.     for (i = 0; i < proc_MaxNumProcesses; i++) {
  984.     pcbPtr = proc_PCBTable[i];
  985.     if (pcbPtr == curProcPtr) {
  986.         continue;
  987.     }
  988.     Proc_Lock(pcbPtr);
  989.     if (pcbPtr->state != PROC_UNUSED) {
  990.         Sync_WakeWaitingProcess(pcbPtr);
  991.     }
  992.     Proc_Unlock(pcbPtr);
  993.     }
  994. }
  995.  
  996.  
  997. /*
  998.  *----------------------------------------------------------------------
  999.  *
  1000.  * Proc_HasPermission --
  1001.  *
  1002.  *      See if the current process has permission to perform an operation on
  1003.  *      a process with the given user id.
  1004.  *
  1005.  * Results:
  1006.  *      TRUE if the current process has the same effective user id
  1007.  *      as the given user id or the current process is super user.
  1008.  *
  1009.  * Side effects:
  1010.  *      None.
  1011.  *
  1012.  *----------------------------------------------------------------------
  1013.  */
  1014.  
  1015. Boolean
  1016. Proc_HasPermission(userID)
  1017.     int         userID;
  1018. {
  1019.     Proc_ControlBlock   *procPtr;
  1020.  
  1021.     procPtr = Proc_GetEffectiveProc();
  1022.     return(procPtr->effectiveUserID == userID ||
  1023.            procPtr->effectiveUserID == PROC_SUPER_USER_ID);
  1024. }
  1025.  
  1026.  
  1027.  
  1028. /*
  1029.  *----------------------------------------------------------------------
  1030.  *
  1031.  * Proc_DoForEveryProc --
  1032.  *
  1033.  *    For every process in the process table, apply *booleanFuncPtr to it.
  1034.  *    If that returns TRUE, apply *actionFuncPtr to it.  This is done by
  1035.  *    passing booleanFuncPtr to a monitored routine and having it
  1036.  *    return an array of qualifying processes.  There is a bit of a race
  1037.  *    condition if something happens to any of those processes after the
  1038.  *    list is returned, but in that case the process is ignored and the next
  1039.  *    one is processed.
  1040.  *
  1041.  *    IgnoreStatus indicates whether the routine should abort if
  1042.  *    a non-SUCCESS status is returned by *actionFuncPtr.
  1043.  *
  1044.  * Results:
  1045.  *    If anything "unexpected" happens, FAILURE will be returned, but in
  1046.  *    general SUCCESS is returned.  If numMatchedPtr is non-NIL, then
  1047.  *    the number of processes matched is returned in *numMatchedPtr.
  1048.  *
  1049.  * Side effects:
  1050.  *    The process table is locked temporarily.  Otherwise, dependent on the
  1051.  *    call-back procedures.
  1052.  *
  1053.  *----------------------------------------------------------------------
  1054.  */
  1055.  
  1056. ReturnStatus
  1057. Proc_DoForEveryProc(booleanFuncPtr, actionFuncPtr, ignoreStatus, numMatchedPtr)
  1058.     Boolean (*booleanFuncPtr) _ARGS_((Proc_ControlBlock *pcbPtr));
  1059.                     /* function to match */
  1060.     ReturnStatus (*actionFuncPtr)_ARGS_((Proc_PID pid));    
  1061.                     /* function to invoke on matches */
  1062.     Boolean ignoreStatus;        /* do not abort if bad ReturnStatus  */
  1063.     int *numMatchedPtr;            /* number of matches in table, or NIL */
  1064. {
  1065.     ReturnStatus status = SUCCESS;
  1066.     Proc_PID *pidArray;
  1067.     int max;
  1068.     int i;
  1069.     int numMatched;
  1070.  
  1071.     max = proc_MaxNumProcesses;
  1072.  
  1073.     pidArray = (Proc_PID *) malloc(sizeof(Proc_PID) * max);
  1074.     numMatched = ProcTableMatch(max, booleanFuncPtr, pidArray);
  1075.     for (i = 0; i < numMatched; i++) {
  1076.     status = (*actionFuncPtr)(pidArray[i]);
  1077.     if ((!ignoreStatus) && (status != SUCCESS)) {
  1078.         break;
  1079.     }
  1080.     }
  1081.     free((Address) pidArray);
  1082.     if (numMatchedPtr != (int *) NIL) {
  1083.     *numMatchedPtr = numMatched;
  1084.     }
  1085.     if (ignoreStatus) {
  1086.     return(SUCCESS);
  1087.     }
  1088.     return(status);
  1089. }
  1090.  
  1091.  
  1092. /*
  1093.  *----------------------------------------------------------------------
  1094.  *
  1095.  * Proc_SetServerPriority --
  1096.  *
  1097.  *    Changes the priority of a server process to the non-interruptable
  1098.  *    value. The pid is assumed to be valid.
  1099.  *
  1100.  * Results:
  1101.  *    None.
  1102.  *
  1103.  * Side effects:
  1104.  *    The process's priority is changed.
  1105.  *
  1106.  *----------------------------------------------------------------------
  1107.  */
  1108.  
  1109. void
  1110. Proc_SetServerPriority(pid)
  1111.     Proc_PID    pid;
  1112. {
  1113.     Proc_GetPCB(pid)->billingRate = PROC_NO_INTR_PRIORITY;
  1114. }
  1115.  
  1116.  
  1117.  
  1118. /*
  1119.  *----------------------------------------------------------------------
  1120.  *
  1121.  * Proc_GetHostIDs --
  1122.  *
  1123.  *    Returns the sprite IDs corresponding to the machines on which
  1124.  *    the current process is effectively executing and on which
  1125.  *    it is physically executing.  These hosts are called the virtualHost
  1126.  *    and physicalHost, respectively.  For an unmigrated process, these
  1127.  *    two are identical.
  1128.  *
  1129.  * Results:
  1130.  *    SUCCESS         The call was successful.
  1131.  *    SYS_ARG_NOACCESS    The user arguments were not accessible.
  1132.  *
  1133.  * Side effects:
  1134.  *    None.
  1135.  *
  1136.  *----------------------------------------------------------------------
  1137.  */
  1138.  
  1139. ReturnStatus
  1140. Proc_GetHostIDs(virtualHostPtr, physicalHostPtr)
  1141.     int    *virtualHostPtr;       /* Buffer to hold virtual host ID. */
  1142.     int    *physicalHostPtr;       /* Buffer to hold physical host ID. */
  1143. {
  1144.  
  1145.     Proc_ControlBlock *procPtr;
  1146.     int host;
  1147.  
  1148.     if (physicalHostPtr != (int *) USER_NIL) {
  1149.  
  1150.     if (Vm_CopyOut(sizeof(int), (Address) &rpc_SpriteID, 
  1151.                 (Address) physicalHostPtr) != SUCCESS) {
  1152.         return(SYS_ARG_NOACCESS);
  1153.     }
  1154.     }
  1155.  
  1156.  
  1157.     if (virtualHostPtr != (int *) USER_NIL) {
  1158.     procPtr = Proc_GetCurrentProc();
  1159.     Proc_Lock(procPtr);
  1160.     host = procPtr->peerHostID;
  1161.     Proc_Unlock(procPtr);
  1162.     if (host == NIL) {
  1163.         host = rpc_SpriteID;
  1164.     }
  1165.     if (Vm_CopyOut(sizeof(int), (Address) &host, 
  1166.                 (Address) virtualHostPtr) != SUCCESS) {
  1167.         return(SYS_ARG_NOACCESS);
  1168.     }
  1169.     }
  1170.  
  1171.     return(SUCCESS);
  1172. }
  1173.  
  1174. /*
  1175.  *----------------------------------------------------------------------
  1176.  *
  1177.  * Proc_PushLockStack --
  1178.  *
  1179.  *    Pushes the given lock type on the lock stack for the process.
  1180.  *
  1181.  * Results:
  1182.  *    None.
  1183.  *
  1184.  * Side effects:
  1185.  *    Stuff is printed if the stack overflows.
  1186.  *
  1187.  *----------------------------------------------------------------------
  1188.  */
  1189.  
  1190. /*ARGSUSED*/
  1191. void
  1192. Proc_PushLockStack(pcbPtr, type, lockPtr)
  1193.     Proc_ControlBlock        *pcbPtr;    /* ptr to pcb to modify */
  1194.     int                type;        /* type of lock */
  1195.     Address            lockPtr;    /* ptr to lock */
  1196.  
  1197. {
  1198. #ifdef LOCKDEP
  1199.     static Boolean    firstOverflow = TRUE;
  1200.  
  1201.     /*
  1202.      *  Modifying the lock stack of a process has to be an atomic operation,
  1203.      *  but we don't want to use a lock to do this, since this is part of
  1204.      *  the code used when locking or unlocking. Using a lock would lead
  1205.      *  to a circularity and probably a deadlock. All we really need to
  1206.      *  prevent is an interrupt handler from grabbing a lock while we're
  1207.      *  modifying the lock stack. A process only modifies its own
  1208.      *  lock stack, so turning off interrupts should be good enough.
  1209.      */
  1210.     DISABLE_INTR();
  1211.     if (pcbPtr->lockStackSize >= PROC_LOCKSTACK_SIZE) {
  1212.     if (firstOverflow) {
  1213.         printf("Proc_PushLockStack: stack overflow in pcb 0x%x.\n",pcbPtr);
  1214.         firstOverflow = FALSE;
  1215.     }
  1216.     goto exit;
  1217.     }
  1218.     if (pcbPtr->lockStackSize < 0 ) {
  1219.     printf("Proc_PushLockStack: stack underflow (%d) in pcb 0x%x.\n",
  1220.            pcbPtr->lockStackSize, pcbPtr);
  1221.         goto exit;
  1222.     }
  1223.     pcbPtr->lockStack[pcbPtr->lockStackSize].type = type;
  1224.     pcbPtr->lockStack[pcbPtr->lockStackSize].lockPtr = lockPtr;
  1225.     pcbPtr->lockStackSize++;
  1226. exit:
  1227.     ENABLE_INTR();
  1228. #endif
  1229. }
  1230.  
  1231. /*
  1232.  *----------------------------------------------------------------------
  1233.  *
  1234.  * Proc_RemoveFromLockStack --
  1235.  *
  1236.  *    Removes the given lock from the stack if it is there.
  1237.  *
  1238.  * Results:
  1239.  *    None.
  1240.  *
  1241.  * Side effects:
  1242.  *    None.
  1243.  *
  1244.  *----------------------------------------------------------------------
  1245.  */
  1246.  
  1247. /*ARGSUSED*/
  1248. void
  1249. Proc_RemoveFromLockStack(pcbPtr, lockPtr)
  1250.     Proc_ControlBlock        *pcbPtr;    /* ptr to pcb to modify */
  1251.     Address            lockPtr;    /* ptr to lock */
  1252. {
  1253. #ifdef LOCKDEP
  1254.     int     i;
  1255.     int        stackTop;
  1256.     Boolean     found = FALSE;
  1257.  
  1258.     DISABLE_INTR();
  1259.     if (pcbPtr->lockStackSize < 0) {
  1260.     ENABLE_INTR();
  1261.     panic("Lock stack underflow (1).\n");
  1262.     goto exit;
  1263.     }
  1264.     if (pcbPtr->lockStackSize == 0) {
  1265.     goto exit;
  1266.     }
  1267.     stackTop = pcbPtr->lockStackSize - 1;
  1268.     for (i = pcbPtr->lockStackSize - 1; i >= 0; i--) {
  1269.     if (pcbPtr->lockStack[i].lockPtr == lockPtr) {
  1270.         pcbPtr->lockStack[i].lockPtr = (Address) NIL;
  1271.         pcbPtr->lockStack[i].type = -1;
  1272.         found = TRUE;
  1273.         break;
  1274.     }
  1275.     }
  1276.     if (!found) {
  1277.     goto exit;
  1278.     }
  1279.     for (i = stackTop; i >= 0; i--) {
  1280.     if (pcbPtr->lockStack[i].lockPtr != (Address) NIL) {
  1281.         break;
  1282.     }
  1283.     }
  1284.     pcbPtr->lockStackSize = i + 1;
  1285.     if (pcbPtr->lockStackSize < 0) {
  1286.     printf("lockStackSize %d\n",pcbPtr->lockStackSize);
  1287.     }
  1288. exit:
  1289.     ENABLE_INTR();
  1290. #endif
  1291. }
  1292.  
  1293. #ifndef LOCKREG
  1294. #ifndef CLEAN_LOCK
  1295. #ifndef CLEAN
  1296. /*
  1297.  *----------------------------------------------------------------------
  1298.  *
  1299.  * Proc_KDump --
  1300.  *
  1301.  *    Prints out an (kluged) proc table with state information.
  1302.  *
  1303.  *    This routine uses several macros to analyse the event data structure:
  1304.  *    ISADDR(x) tests if x is a valid address.
  1305.  *    ISSTR(x) tests if x is a pointer to a valid string.
  1306.  *    ISALIGN(x) tests if x is an aligned address.
  1307.  *    ISBOOL(x) tests if x is a boolean.
  1308.  *    ISSMALL(x) tests is x is a small integer.
  1309.  *    ISLIST(x) tests if x points to a List_Links structure.
  1310.  *    ISPCB(x) tests if x points to a Proc_ControlBlock structure.
  1311.  *    ISHANDLE(x) tests is x points to a Fs_HandleHeader structure.
  1312.  *    FIELD(x,type,field) is x->type.field
  1313.  *
  1314.  * Results:
  1315.  *    SUCCESS.
  1316.  *
  1317.  * Side effects:
  1318.  *    Prints stuff to screen.
  1319.  *
  1320.  *
  1321.  *----------------------------------------------------------------------
  1322.  */
  1323. #define INT(x)    ((int)(x))
  1324. #define INTP(x)    ((int *)(x))
  1325. #define ISADDRR(x,range)  ((INT(x)&1)==0 && Dbg_InRange((unsigned)(x),2,FALSE)\
  1326.         && Dbg_InRange(((unsigned)(x))+(range)-2,2,FALSE))
  1327. #define ISADDR(x)    ISADDRR(x,sizeof(int))
  1328. #define ISSTR(x)    (ISADDRR(x,20) && \
  1329.     (strncpy(buf,(char *)(x),20),strlen(buf)<20) && isprint(buf[0]))
  1330. #define    ISSTRZ(x)    (INT(x)==0 || ISSTR(x))
  1331. #define ISALIGN(x)    (ISADDR(x) && (INT(x)&3)==0)
  1332. #define ISALIGNZ(x)    (INT(x)==0 || ISALIGN(x))
  1333. /* sun3 test-and-set sets to 0x80000000, sun4 to 0xff000000 */
  1334. #define ISBOOL(x)    (INT(x)==0||INT(x)==1||INT(x)==0x80000000||\
  1335.             INT(x)==0xff000000)
  1336. #define ISSMALL(x)    (INT(x)>=0&&INT(x)<20)
  1337. #define ISPCBZ(x)    (INT(x)==0||ISPCB(x))
  1338. #define OFF(type,field) (INTP(&(((type *)0)->field))-INTP(0))
  1339. #define FIELD(var,type,field)    (((type *)(var))->field)
  1340. #define P_cb    Proc_ControlBlock
  1341. #define Fc_b    Fscache_Block
  1342. #define Fc_fi    Fscache_FileInfo
  1343. #define F_hh    Fs_HandleHeader
  1344. #define L_L    List_Links
  1345. #define HANDLENAME(x)    (Fsutil_HandleName((Fs_HandleHeader *)(x)))
  1346. #define PRINTHANDLE(str,handle)    printf("%s: \"%s\" (handle locked by %x)",\
  1347.         str, HANDLENAME(handle), handle->lockProcPtr)
  1348. char buf[21] = {0};
  1349.  
  1350. static int ISLIST(x)
  1351. List_Links *x;
  1352. {
  1353.     return ISADDRR(x,sizeof(List_Links)) && ISADDR(x->prevPtr) &&
  1354.         ISADDR(x->nextPtr);
  1355. }
  1356.  
  1357. static int ISPCB(x)
  1358. Proc_ControlBlock *x;
  1359. {
  1360.     return ISADDRR(x,sizeof(Proc_ControlBlock)) && ISLIST(&x->links) &&
  1361.        ISSMALL(x->processor) && ISLIST(&x->childListHdr) &&
  1362.        x->processID <= 0xfffff;
  1363. }
  1364.  
  1365. static int ISHANDLE(x)
  1366. Fs_HandleHeader *x;
  1367. {
  1368.     return ISADDRR(x,sizeof(Fs_HandleHeader)) && ISLIST(&x->lruLinks) &&
  1369.        ISBOOL(x->unlocked.waiting) && ISSMALL(x->refCount) &&
  1370.        ISSTRZ(x->name) && 
  1371.        (x->lockProcPtr == (Proc_ControlBlock *)NIL
  1372.             || ISPCB(x->lockProcPtr));
  1373. }
  1374.  
  1375. static int ISRPCCLIENT(x)
  1376. RpcClientChannel *x;
  1377. {
  1378.     int i;
  1379.     if (!ISADDRR(x,sizeof(RpcClientChannel))) return 0;
  1380.     for (i=0;i<rpcNumChannels;i++) {
  1381.     if (rpcChannelPtrPtr[i] == x) return 1;
  1382.     }
  1383.     return 0;
  1384. }
  1385.  
  1386. static int ISRPCSERVER(x)
  1387. RpcServerState *x;
  1388. {
  1389.     int i;
  1390.     if (!ISADDRR(x,sizeof(RpcServerState))) return 0;
  1391.     for (i=0;i<rpcMaxServers;i++) {
  1392.     if (rpcServerPtrPtr[i] == x) return 1;
  1393.     }
  1394.     return 0;
  1395. }
  1396.  
  1397. static int ISSERVERPROC(x)
  1398. ServerInfo *x;
  1399. {
  1400.     int i;
  1401.     if (!ISADDRR(x,sizeof(ServerInfo))) return 0;
  1402.     for (i=0;i<proc_NumServers;i++) {
  1403.     if (serverInfoTable+i == x) return 1;
  1404.     }
  1405.     return 0;
  1406. }
  1407.  
  1408. static int ISLOCK(x)
  1409. Sync_Lock *x;
  1410. {
  1411.     return ISADDRR(x,sizeof(Sync_Lock)) && ISBOOL(x->inUse) &&
  1412.         ISBOOL(x->waiting) && ISSTR(x->name) && ISALIGNZ(x->holderPC) &&
  1413.         ISPCBZ(x->holderPCBPtr);
  1414. }
  1415.  
  1416. static int ISSEM(x)
  1417. Sync_Semaphore *x;
  1418. {
  1419.     return ISADDRR(x,sizeof(Sync_Semaphore)) && ISSMALL(x->value) &&
  1420.         ISSTR(x->name) && ISALIGNZ(x->holderPC) && ISPCBZ(x->holderPCBPtr);
  1421. }
  1422.  
  1423. typedef struct LockEntry {
  1424.     int    addr;        /* Address (event) associated with the lock. */
  1425.     char *name;        /* Name of the lock event. */
  1426. } LockEntry;
  1427.  
  1428. extern Sync_Condition cleanBlockCondition, writeBackComplete,
  1429.     closeCondition, lruDone, debugListCondition, familyCondition,
  1430.     migrateCondition, evictCondition, recovCondition, recovPingCondition,
  1431.     rpcDaemon, freeChannels, signalCondition, codeSegCondition,
  1432.     cleanCondition, swapDownCondition, mappingCondition, swapFileCondition;
  1433.  
  1434. LockEntry locks[] = {
  1435.     (int)&cleanBlockCondition, "cleanBlockCondition",
  1436.     (int)&writeBackComplete, "writeBackComplete",
  1437.     (int)&closeCondition, "closeCondition",
  1438.     (int)&lruDone, "lruDone",
  1439.     (int)&debugListCondition, "debugListCondition",
  1440.     (int)&familyCondition, "familyCondition",
  1441.     (int)&migrateCondition, "migrateCondition",
  1442.     (int)&evictCondition, "evictCondition",
  1443.     (int)&recovCondition, "recovCondition",
  1444.     (int)&rpcDaemon, "rpcDaemon",
  1445.     (int)&freeChannels, "freeChannels",
  1446.     (int)&signalCondition, "signalCondition",
  1447.     (int)&codeSegCondition, "codeSegCondition",
  1448.     (int)&cleanCondition, "cleanCondition",
  1449.     (int)&swapDownCondition, "swapDownCondition",
  1450.     (int)&mappingCondition, "mappingCondition",
  1451.     (int)&swapFileCondition, "swapFileCondition",
  1452.     (int)&recovPingCondition, "recovPingCondition",
  1453.     0, 0
  1454. };
  1455.  
  1456. /*ARGSUSED*/
  1457. void
  1458. Proc_KDump(dummy)
  1459.     ClientData dummy;        /* unused - see dump.c:eventTable */
  1460. {
  1461.     int i;
  1462.     Proc_ControlBlock *procPtr, *tmpProcPtr;
  1463.     int *event;
  1464.     LockEntry *lockPtr;
  1465.     Fscache_FileInfo *cacheInfoPtr;
  1466.     Fs_HandleHeader *handlePtr;
  1467.     RpcClientChannel *rpcClientPtr;
  1468.     RpcServerState *rpcServerPtr;
  1469.     ServerInfo *serverProcPtr;
  1470.     int match;
  1471.  
  1472.     for (i = 0; i < proc_MaxNumProcesses; i++) {
  1473.     procPtr = proc_PCBTable[i];
  1474.     match = 0;
  1475.     if (procPtr->state == PROC_WAITING) {
  1476.         printf("%8x", procPtr->processID);
  1477.         if (procPtr->argString != (Address) NIL) {
  1478.         char cmd[30];
  1479.         char *space;
  1480.  
  1481.         (void) strncpy(cmd, procPtr->argString, 30);
  1482.         space = strchr(cmd, ' ');
  1483.         if (space != (char *) NULL) {
  1484.             *space = '\0';
  1485.         } else {
  1486.             cmd[29] = '\0';
  1487.         }
  1488.         printf("(%s)", cmd);
  1489.         }
  1490.         printf(": waiting on ");
  1491.         event = (int *)procPtr->event;
  1492.         if (ISADDR(event)) {
  1493.         for (lockPtr = locks ; lockPtr->addr != 0; lockPtr++) {
  1494.             if ((int)event == lockPtr->addr) {
  1495.             printf("condition \"%s\"\n", lockPtr->name);
  1496.             goto found;
  1497.             }
  1498.         }
  1499.         if (ISLOCK((Sync_Lock *)event)) {
  1500.             /* Sync_Lock / Sync_KernelLock */
  1501.             printf("lock \"%s\" at %x", (char *)(event[2]), 
  1502.                 (int)event[3]);
  1503.             if (ISPCB((P_cb *)event[4])) {
  1504.                 printf(" held by process %x",
  1505.                 ((Proc_ControlBlock *)(event[4]))->processID);
  1506.             }
  1507.         } else if (ISPCB((P_cb *)event)) {
  1508.             /* Proc_ControlBlock */
  1509.             printf("timer %x",
  1510.                 ((Proc_ControlBlock *)event)->processID);
  1511.         } else if (ISSEM((Sync_Semaphore *)event)) {
  1512.            /* Sync_Semaphore */
  1513.             printf("semaphore \"%s\" at %x",
  1514.                 (char *)(event[1]), (int)(event[2]));
  1515.             if (ISPCB((P_cb *)event[3])) {
  1516.             printf(" held by process %x",
  1517.                 ((Proc_ControlBlock *)(event[3]))->processID);
  1518.             }
  1519.         } else if (ISBOOL(event[0])) {
  1520.             /* Sync_Condition */
  1521.             handlePtr = (F_hh *)(event-OFF(F_hh,unlocked));
  1522.             if (ISHANDLE(handlePtr)) {
  1523.             PRINTHANDLE("handle: \"unlocked\"", handlePtr);
  1524.             match++;
  1525.             }
  1526.             handlePtr = (F_hh *)(FIELD(event-OFF(Fc_fi,noDirtyBlocks),
  1527.                 Fc_fi, hdrPtr));
  1528.             if (ISHANDLE(handlePtr)) {
  1529.             PRINTHANDLE("cache block: \"noDirtyBlocks\"",
  1530.                 handlePtr);
  1531.             match++;
  1532.             }
  1533.             /* See if intPtr is a cacheInfoPtr */
  1534.             cacheInfoPtr = (Fc_fi *)FIELD(event-OFF(Fc_b,ioDone), Fc_b,
  1535.                 cacheInfoPtr);
  1536.             if (ISADDRR(cacheInfoPtr,sizeof(Fc_fi)) &&
  1537.                 ISHANDLE(cacheInfoPtr->hdrPtr)) {
  1538.             PRINTHANDLE("cache block: \"ioDone\"",
  1539.                 cacheInfoPtr->hdrPtr);
  1540.             match++;
  1541.             }
  1542.             tmpProcPtr = (P_cb *)(event-OFF(P_cb,waitCondition));
  1543.             if (ISPCB(tmpProcPtr)) {
  1544.             printf("PCB: \"waitCondition\" ");
  1545.             match++;
  1546.             }
  1547.             tmpProcPtr = (P_cb *)(event-OFF(P_cb,lockedCondition));
  1548.             if (ISPCB(tmpProcPtr)) {
  1549.             printf("PCB: \"lockedCondition\" ");
  1550.             match++;
  1551.             }
  1552.             serverProcPtr = (ServerInfo *)(event-
  1553.                 OFF(ServerInfo, condition));
  1554.             if (ISSERVERPROC(serverProcPtr)) {
  1555.             printf("ServerProc: \"condition\" ");
  1556.             if (serverProcPtr->flags & ENTRY_INUSE) {
  1557.                 printf("INUSE ");
  1558.             }
  1559.             if (serverProcPtr->flags & SERVER_BUSY) {
  1560.                 printf("BUSY ");
  1561.             }
  1562.             if (serverProcPtr->flags & FUNC_PENDING) {
  1563.                 printf("PENDING ");
  1564.             }
  1565.             match++;
  1566.             }
  1567.             rpcClientPtr = (RpcClientChannel *)(event-
  1568.                 OFF(RpcClientChannel, waitCondition));
  1569.             if (ISRPCCLIENT(rpcClientPtr)) {
  1570.             printf("RPC client: \"waitCondition\", server %d ",
  1571.                 rpcClientPtr->serverID);
  1572.             if (rpcClientPtr->state & CHAN_FREE) printf("FREE ");
  1573.             if (rpcClientPtr->state & CHAN_BUSY) printf("BUSY ");
  1574.             if (rpcClientPtr->state & CHAN_WAITING) printf("WAIT ");
  1575.             if (rpcClientPtr->state & CHAN_TIMEOUT) printf("TIME ");
  1576.             if (rpcClientPtr->state & CHAN_FRAGMENTING) {
  1577.                 printf("FRAG ");
  1578.             }
  1579.             match++;
  1580.             }
  1581.             rpcServerPtr = (RpcServerState *)(event-
  1582.                 OFF(RpcServerState, waitCondition));
  1583.             if (ISRPCSERVER(rpcServerPtr)) {
  1584.             printf("RPC server:\"waitCondition\", client %d ",
  1585.                 rpcServerPtr->clientID);
  1586.             if (rpcServerPtr->state & SRV_NOTREADY) {
  1587.                 printf("NOTREADY ");
  1588.             }
  1589.             if (rpcServerPtr->state & SRV_FREE) printf("FREE ");
  1590.             if (rpcServerPtr->state & SRV_BUSY) printf("BUSY ");
  1591.             if (rpcServerPtr->state & SRV_WAITING) printf("WAIT ");
  1592.             if (rpcServerPtr->state & SRV_AGING) printf("AGING ");
  1593.             if (rpcServerPtr->state & SRV_FRAGMENT) printf("FRAG ");
  1594.             if (rpcServerPtr->state & SRV_NO_REPLY) {
  1595.                 printf("NO_REPLY ");
  1596.             }
  1597.             if (rpcServerPtr->state & SRV_STUCK) printf("STUCK ");
  1598.             match++;
  1599.             }
  1600.             handlePtr = (F_hh *)(event-OFF(Fsrmt_IOHandle,
  1601.             recovery.reopenComplete));
  1602.             if (ISHANDLE(handlePtr)) {
  1603.             PRINTHANDLE("\"recovery.reopenComplete\"", handlePtr);
  1604.             match++;
  1605.             }
  1606.             if (!match) {
  1607.             printf("condition %x", (int)event);
  1608.             } else if (match>1) {
  1609.             printf("(Ambiguous)");
  1610.             }
  1611.         } else {
  1612.             printf("event %x", (int)event);
  1613.         }
  1614.         } else if ((int)event == -1) {
  1615.         printf("wakeup signal");
  1616.         } else {
  1617.         printf("event? %x", (int)event);
  1618.         }
  1619.         printf("\n");
  1620. found:;
  1621.     }
  1622.     }
  1623. }
  1624. #define KDUMP
  1625. #endif
  1626. #endif
  1627. #endif
  1628.  
  1629. #ifndef KDUMP
  1630. /* ARGSUSED */
  1631. ReturnStatus
  1632. Proc_KDump(dummy) 
  1633.     ClientData dummy;
  1634.     return SUCCESS;
  1635. }
  1636. #endif
  1637.